package com.pzr.soccer.service;

import com.pzr.soccer.consts.RedisConst;
import com.pzr.soccer.dao.PlanRepository;
import com.pzr.soccer.domain.Plan;
import com.pzr.soccer.domain.game.GameWrapper;
import com.pzr.soccer.domain.message.PlanMessage;
import com.pzr.soccer.uitl.FindRightGameForPlan;
import com.pzr.soccer.watched.PlanObserver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @Author pzr
 * @date:2021-12-10-17:09
 * @Description:
 **/
@Service
@Slf4j
public class ScanChangeGameProcessor implements PlanObserver {
public static final String PlanMessage_Type_MatchCondition="符合条件";
public static final String PlanMessage_Type_MatchResult="符合结果";
    @Autowired
    PlanRepository planRepository;
   @Autowired
   RedisTemplate<String,Object> redisTemplate;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Autowired
    MongoOperations mongoOperations;
   @Autowired
    FanoutExchange planMatchMessageExchange;

    private CopyOnWriteArrayList<Plan> plans = new CopyOnWriteArrayList<>();

    public void initPlans(){
        this.plans.clear();
        List<Plan> plans1=planRepository.requestLightly();
        this.plans.addAll(plans1);
    }

    public void addOrUpdatePlan(Plan plan){
        //更新
        if(plan.getId()!=null){
            for(Plan p:this.plans){
                if(plan.getId().equals(p.getId())){
                    this.plans.remove(p);
                    break;
                }
            }
        }
        this.plans.add(plan);
    }
 public CopyOnWriteArrayList<Plan> getPlans(){
        return  this.plans;
 }



    public void scanMatchForPlans(GameWrapper wrapper){
      //  log.info(String.format("handel %s for %d plans ",wrapper.getId(),this.plans.size()));
        for(Plan plan:this.plans){
            String key_suffix=plan.getId()+"|"+wrapper.getId();
            //test precondition
            if(!redisTemplate.hasKey(RedisConst.Plan_Scanning_MeetPreCondition_Prefix+key_suffix)){ //未处理过的
                if(FindRightGameForPlan.testCondition(wrapper,plan)){
                    log.info(String.format("find match %s pre-condition for plan %s",wrapper.getId(),plan.getName()));
                    saveMeetPreConditionToRedis(wrapper,plan);
                    SendMessageToQueue( wrapper,  plan,PlanMessage_Type_MatchCondition);

                    plan.setMatchPreCondition(plan.getMatchPreCondition()+1);
                    plan.getMatchesId().add(wrapper.getGame().getId());
                    planRepository.updateAfterScanGame(plan);
                }
            }

            //test result

            if(redisTemplate.hasKey(RedisConst.Plan_Scanning_MeetPreCondition_Prefix+key_suffix)&&       //已经符合预设条件
                    !redisTemplate.hasKey(RedisConst.Plan_Scanning_MeetResult+key_suffix)){        //并且未处理过的
                if(FindRightGameForPlan.testResult(wrapper,plan)){
                    log.info(String.format("find match %s result for plan %s",wrapper.getId(),plan.getName()));
                    saveMeetResultToRedis(wrapper,plan);
                    SendMessageToQueue( wrapper,  plan,PlanMessage_Type_MatchResult);

                    plan.setMatchResult(plan.getMatchResult()+1);
                    plan.getCorrectMatchesId().add(wrapper.getGame().getId());
                    planRepository.updateAfterScanGame(plan);
                }
            }

        }

    }

    private void saveMeetResultToRedis(GameWrapper wrapper, Plan plan) {
        String key_suffix=plan.getId()+"|"+wrapper.getId();
        redisTemplate.opsForValue().set(RedisConst.Plan_Scanning_MeetResult+key_suffix,"");
    }

    private void SendMessageToQueue(GameWrapper wrapper, Plan plan,String messageType) {
        PlanMessage message=new PlanMessage();
       message.setUserId(plan.getUserId());
       message.setPlanId(plan.getId());
       message.setPlanName(plan.getName());
       message.setHome(wrapper.getGame().getHome());
       message.setMatchId(wrapper.getGame().getId());
       message.setGameKickOff(wrapper.getGame().getKickOff());
       message.setGameCurrentTimeStr(wrapper.getCurrentTimeStr());
       message.setType(messageType);
        message.setLeague(wrapper.getGame().getLeague());
        message.setAway(wrapper.getGame().getAway());
        message.setEmail(plan.getUserEmail());
        message.setMobile(plan.getUserMobile());
     //........
        System.out.println("send message:"+message.getMatchId());
       rabbitTemplate.convertAndSend("FanoutExChange_Plan_Match_Message",null,message);
    }


    private void saveMeetPreConditionToRedis(GameWrapper wrapper, Plan plan) {
        String key_suffix=plan.getId()+"|"+wrapper.getId();
        redisTemplate.opsForValue().set(RedisConst.Plan_Scanning_MeetPreCondition_Prefix+key_suffix,"");
    }


    //观察数据库的改变
    @Override
    public void handleUpdate(Plan plan) {
        log.info("note a plan has been updated!,handle..");
        plan.getCorrectMatchesId().clear();
        plan.getMatchesId().clear();
        addOrUpdatePlan(plan);
    }

    @Override
    public void handleRemove(Plan plan) {
        log.info("note a plan has been removed!,handle..");
        for(Plan plan1:this.plans){
            if(plan.getId().equals(plan1.getId()))
            {
                this.plans.remove(plan1);
                break;
            }
        }
    }
}
